package org.ysh.core.utils;

import com.adobe.xmp.XMPMeta;
import com.adobe.xmp.XMPMetaFactory;
import com.adobe.xmp.impl.XMPIteratorImpl;
import com.adobe.xmp.properties.XMPPropertyInfo;

import java.io.*;

import java.util.Arrays;

import java.util.HashMap;
import java.util.Iterator;

import java.util.Map;

/**
 * 图片读取添加XMP数据:
 * <p>
 * 实现思路：获取图片中xmpmeta块信息，编辑替换
 *
 * @author lijiongquan
 */

public class XMPUtil {

    private final byte[] OPEN_ARR = "".getBytes();

    private final byte[] CLOSE_ARR = "".getBytes();
    private final String namespace = "http://www.xxxx.com.cn/xxxx/1.0/";

    private final String xmpTag = "xxxx:";

    private String orgPath;

    private String destPath;

    private Map xmpMap;

    /**
     * 添加图片XMP数据
     *
     * @param orgPath  图片路径
     * @param destPath 生成图片路径
     * @param xmpMap   添加数据集
     */

    public void changeImgXMP(String orgPath, String destPath, Map xmpMap) {

        this.orgPath = orgPath;

        this.destPath = destPath;

        this.xmpMap = xmpMap;

        try {
            setXMP();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void setXMP() throws Exception {

        File orgFile = new File(orgPath);

        File destFile = new File(destPath);

        if (destFile.exists()) {

            destFile.delete();

            destFile.createNewFile();

        }

        FileInputStream in = new FileInputStream(orgFile);

        ByteArrayOutputStream out = new ByteArrayOutputStream();

        copy(in, out);

        byte[] fileData = out.toByteArray();

        int openIdx = indexOf(fileData, OPEN_ARR, 0);

        if (openIdx > 0) {

            int closeIdx = indexOf(fileData, CLOSE_ARR, openIdx + 1) + CLOSE_ARR.length;

            byte[] beforeArr = Arrays.copyOfRange(fileData, 0, openIdx);

            byte[] afterArr = Arrays.copyOfRange(fileData, closeIdx + 1, fileData.length);

            byte[] xmpArr = Arrays.copyOfRange(fileData, openIdx, closeIdx);

            XMPMeta xmpMeta = XMPMetaFactory.parseFromBuffer(xmpArr);

            XMPMetaFactory.getSchemaRegistry().registerNamespace(namespace, xmpTag);

            addXMPMeta(xmpMeta);

            printXMPMeta(xmpMeta);

            ByteArrayOutputStream xmpOut = new ByteArrayOutputStream();

            XMPMetaFactory.serialize(xmpMeta, xmpOut);

            byte[] xmpArrNew = xmpOut.toByteArray();

            FileOutputStream outputStream = new FileOutputStream(destFile);

            wirteByte(outputStream, beforeArr);

            wirteByte(outputStream, xmpArrNew);

            wirteByte(outputStream, afterArr);

            outputStream.close();

        }

    }

    private void wirteByte(OutputStream out, byte[] bytes) throws Exception {

        out.write(bytes);

        out.flush();

    }

    private void addXMPMeta(XMPMeta xmpMeta) throws Exception {

        Iterator iter = xmpMap.keySet().iterator();

        while (iter.hasNext()) {

            String key = (String) iter.next();

            String value = (String) xmpMap.get(key);

            xmpMeta.setProperty(namespace, xmpTag + key, value);

        }

    }

    private void printXMPMeta(XMPMeta xmpMeta) throws Exception {

        XMPIteratorImpl xmpIterator = (XMPIteratorImpl) xmpMeta.iterator();

        while (xmpIterator.hasNext()) {

            XMPPropertyInfo obj = (XMPPropertyInfo) xmpIterator.next();

            System.out.println(obj.getNamespace() + "--" + obj.getPath() + "--" + obj.getValue());

        }

    }

    private int indexOf(byte[] arr, byte[] sub, int start) {

        int subIdx = 0;

        for (int x = start; x < arr.length; x++) {

            if (arr[x] == sub[subIdx]) {

                if (subIdx == sub.length - 1) {

                    return x - subIdx;

                }

                subIdx++;

            } else {

                subIdx = 0;

            }

        }

        return -1;

    }

    private void copy(InputStream in, OutputStream out) throws Exception {

        int len = -1;

        byte[] buf = new byte[1024];

        while ((len = in.read(buf)) >= 0) {

            out.write(buf, 0, len);

        }

        in.close();

        out.close();

    }

    public static void main(String[] args) {
        Map xmpMap = new HashMap<>();

        xmpMap.put("testKey","testValue");

        xmpMap.put("testKey222","testValue22");

        XMPUtil xmpUtil = new XMPUtil();

        xmpUtil.changeImgXMP("D:\\BaiduNetdiskDownload\\5179-001-ZY·BH-Y-00002\\001.tif","D:\\BaiduNetdiskDownload\\5179-001-ZY·BH-Y-00002\\001_bak.tif", xmpMap);

    }

}
